package com.aviatorscript.aviatorscript.service;

import com.aviatorscript.aviatorscript.cache.RuleCacheManager;
import com.aviatorscript.aviatorscript.dto.FieldMappingRuleDTO;
import com.aviatorscript.aviatorscript.dto.TransformRuleDTO;
import com.aviatorscript.aviatorscript.engine.DataTransformEngine;
import com.aviatorscript.aviatorscript.entity.FieldMappingRule;
import com.aviatorscript.aviatorscript.entity.TransformRule;
import com.aviatorscript.aviatorscript.mapper.FieldMappingRuleMapper;
import com.aviatorscript.aviatorscript.mapper.TransformRuleMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 转换规则业务逻辑服务类
 * 提供转换规则的完整业务逻辑处理，包括CRUD操作、缓存管理、数据转换执行等
 */
@Slf4j
@Service
public class TransformRuleService {

    @Autowired
    private TransformRuleMapper transformRuleMapper;

    @Autowired
    private FieldMappingRuleMapper fieldMappingRuleMapper;

    @Autowired
    private RuleCacheManager ruleCacheManager;

    @Autowired
    private DataTransformEngine dataTransformEngine;

    /**
     * 创建转换规则
     * @param ruleDTO 转换规则DTO
     * @return 创建后的转换规则DTO
     */
    @Transactional(rollbackFor = Exception.class)
    public TransformRuleDTO createRule(TransformRuleDTO ruleDTO) {
        log.info("开始创建转换规则: {}", ruleDTO.getRuleCode());
        
        // 参数校验
        validateRuleDTO(ruleDTO);
        
        // 检查规则编码是否已存在
        TransformRule existingRule = transformRuleMapper.selectByRuleCode(ruleDTO.getRuleCode());
        if (existingRule != null) {
            throw new RuntimeException("规则编码已存在: " + ruleDTO.getRuleCode());
        }

        try {
            // 转换DTO为实体
            TransformRule rule = new TransformRule();
            BeanUtils.copyProperties(ruleDTO, rule);
            rule.setCreateTime(LocalDateTime.now());
            rule.setUpdateTime(LocalDateTime.now());
            rule.setVersion(1);
            rule.setEnabled(true);
            rule.setCompileStatus(false);
            rule.setExecuteCount(0L);

            // 插入转换规则
            int result = transformRuleMapper.insert(rule);
            if (result <= 0) {
                throw new RuntimeException("创建转换规则失败");
            }

            // 处理字段映射规则
            if (!CollectionUtils.isEmpty(ruleDTO.getFieldMappingRules())) {
                List<FieldMappingRule> fieldMappings = convertFieldMappingDTOs(ruleDTO.getFieldMappingRules(), rule.getId());
                int mappingResult = fieldMappingRuleMapper.batchInsert(fieldMappings);
                if (mappingResult <= 0) {
                    throw new RuntimeException("创建字段映射规则失败");
                }
            }

            // 刷新缓存（异步）
            refreshRuleCacheAsync(rule.getRuleCode());

            // 返回创建结果
            TransformRuleDTO resultDTO = new TransformRuleDTO();
            BeanUtils.copyProperties(rule, resultDTO);
            
            log.info("转换规则创建成功: {}", rule.getRuleCode());
            return resultDTO;
            
        } catch (Exception e) {
            log.error("创建转换规则失败: {}", ruleDTO.getRuleCode(), e);
            throw new RuntimeException("创建转换规则失败: " + e.getMessage(), e);
        }
    }

    /**
     * 更新转换规则
     * @param ruleDTO 转换规则DTO
     * @return 更新后的转换规则DTO
     */
    @Transactional(rollbackFor = Exception.class)
    public TransformRuleDTO updateRule(TransformRuleDTO ruleDTO) {
        log.info("开始更新转换规则: {}", ruleDTO.getRuleCode());
        
        // 参数校验
        if (ruleDTO.getId() == null) {
            throw new RuntimeException("更新规则时ID不能为空");
        }
        validateRuleDTO(ruleDTO);

        try {
            // 查询原规则
            TransformRule existingRule = transformRuleMapper.selectById(ruleDTO.getId());
            if (existingRule == null) {
                throw new RuntimeException("规则不存在，ID: " + ruleDTO.getId());
            }

            // 检查规则编码是否被其他规则使用
            if (!existingRule.getRuleCode().equals(ruleDTO.getRuleCode())) {
                TransformRule codeCheckRule = transformRuleMapper.selectByRuleCode(ruleDTO.getRuleCode());
                if (codeCheckRule != null && !codeCheckRule.getId().equals(ruleDTO.getId())) {
                    throw new RuntimeException("规则编码已被其他规则使用: " + ruleDTO.getRuleCode());
                }
            }

            // 更新转换规则
            TransformRule rule = new TransformRule();
            BeanUtils.copyProperties(ruleDTO, rule);
            rule.setUpdateTime(LocalDateTime.now());
            rule.setCompileStatus(false); // 规则更新后需要重新编译
            
            int result = transformRuleMapper.updateById(rule);
            if (result <= 0) {
                throw new RuntimeException("更新转换规则失败");
            }

            // 删除原有字段映射规则
            fieldMappingRuleMapper.deleteByRuleId(rule.getId());

            // 插入新的字段映射规则
            if (!CollectionUtils.isEmpty(ruleDTO.getFieldMappingRules())) {
                List<FieldMappingRule> fieldMappings = convertFieldMappingDTOs(ruleDTO.getFieldMappingRules(), rule.getId());
                int mappingResult = fieldMappingRuleMapper.batchInsert(fieldMappings);
                if (mappingResult <= 0) {
                    throw new RuntimeException("更新字段映射规则失败");
                }
            }

            // 更新版本号
            transformRuleMapper.incrementVersion(rule.getId());

            // 刷新缓存（异步）
            refreshRuleCacheAsync(rule.getRuleCode());

            // 返回更新结果
            TransformRuleDTO resultDTO = new TransformRuleDTO();
            BeanUtils.copyProperties(rule, resultDTO);
            
            log.info("转换规则更新成功: {}", rule.getRuleCode());
            return resultDTO;
            
        } catch (Exception e) {
            log.error("更新转换规则失败: {}", ruleDTO.getRuleCode(), e);
            throw new RuntimeException("更新转换规则失败: " + e.getMessage(), e);
        }
    }

    /**
     * 删除转换规则
     * @param id 规则ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteRule(Long id) {
        log.info("开始删除转换规则，ID: {}", id);
        
        try {
            // 查询规则
            TransformRule rule = transformRuleMapper.selectById(id);
            if (rule == null) {
                throw new RuntimeException("规则不存在，ID: " + id);
            }

            // 删除字段映射规则
            fieldMappingRuleMapper.deleteByRuleId(id);

            // 删除转换规则
            int result = transformRuleMapper.deleteById(id);
            if (result <= 0) {
                throw new RuntimeException("删除转换规则失败");
            }

            // 从缓存中移除
            ruleCacheManager.removeRule(rule.getRuleCode());
            
            log.info("转换规则删除成功: {}", rule.getRuleCode());
            
        } catch (Exception e) {
            log.error("删除转换规则失败，ID: {}", id, e);
            throw new RuntimeException("删除转换规则失败: " + e.getMessage(), e);
        }
    }

    /**
     * 根据ID查询转换规则
     * @param id 规则ID
     * @return 转换规则DTO
     */
    public TransformRuleDTO getRuleById(Long id) {
        TransformRule rule = transformRuleMapper.selectById(id);
        if (rule == null) {
            return null;
        }

        // 查询字段映射规则
        List<FieldMappingRule> fieldMappings = fieldMappingRuleMapper.selectByRuleId(id);
        
        // 转换为DTO
        return convertToRuleDTO(rule, fieldMappings);
    }

    /**
     * 根据规则编码查询转换规则
     * @param ruleCode 规则编码
     * @return 转换规则DTO
     */
    public TransformRuleDTO getRuleByCode(String ruleCode) {
        TransformRule rule = transformRuleMapper.selectByRuleCode(ruleCode);
        if (rule == null) {
            return null;
        }

        // 查询字段映射规则
        List<FieldMappingRule> fieldMappings = fieldMappingRuleMapper.selectByRuleId(rule.getId());
        
        // 转换为DTO
        return convertToRuleDTO(rule, fieldMappings);
    }

    /**
     * 分页查询转换规则列表
     * @param page 页码
     * @param size 页面大小
     * @param enabled 是否启用（可选）
     * @param keyword 关键词搜索（可选）
     * @return 分页结果
     */
    public IPage<TransformRuleDTO> getRuleList(int page, int size, Boolean enabled, String keyword) {
        Page<TransformRule> pageParam = new Page<>(page, size);
        
        QueryWrapper<TransformRule> queryWrapper = new QueryWrapper<>();
        
        // 条件过滤
        if (enabled != null) {
            queryWrapper.eq("enabled", enabled);
        }
        if (StringUtils.hasText(keyword)) {
            queryWrapper.and(wrapper -> wrapper
                .like("rule_code", keyword)
                .or()
                .like("rule_name", keyword)
                .or()
                .like("description", keyword)
            );
        }
        
        // 按更新时间倒序
        queryWrapper.orderByDesc("update_time");
        
        IPage<TransformRule> resultPage = transformRuleMapper.selectPage(pageParam, queryWrapper);
        
        // 转换为DTO分页结果
        IPage<TransformRuleDTO> dtoPage = new Page<>(page, size);
        dtoPage.setTotal(resultPage.getTotal());
        dtoPage.setPages(resultPage.getPages());
        
        List<TransformRuleDTO> dtoList = resultPage.getRecords().stream()
            .map(rule -> {
                TransformRuleDTO dto = new TransformRuleDTO();
                BeanUtils.copyProperties(rule, dto);
                return dto;
            })
            .collect(Collectors.toList());
        
        dtoPage.setRecords(dtoList);
        return dtoPage;
    }

    /**
     * 执行数据转换
     * @param ruleCode 规则编码
     * @param sourceData 源数据对象
     * @param targetClass 目标类型Class
     * @return 转换后的目标对象
     */
    public <T> T executeTransform(String ruleCode, Object sourceData, Class<T> targetClass) {
        log.info("执行数据转换，规则: {}, 目标类型: {}", ruleCode, targetClass.getName());
        
        try {
            // 更新执行统计
            updateExecuteStatistics(ruleCode);
            
            // 执行转换
            T result = dataTransformEngine.transform(ruleCode, sourceData, targetClass);
            
            log.info("数据转换成功，规则: {}", ruleCode);
            return result;
            
        } catch (Exception e) {
            log.error("数据转换失败，规则: {}", ruleCode, e);
            throw new RuntimeException("数据转换失败: " + e.getMessage(), e);
        }
    }

    /**
     * 刷新指定规则缓存
     * @param ruleCode 规则编码
     */
    public void refreshRuleCache(String ruleCode) {
        log.info("刷新规则缓存: {}", ruleCode);
        try {
            ruleCacheManager.refreshRule(ruleCode);
        } catch (Exception e) {
            log.error("刷新规则缓存失败: {}", ruleCode, e);
            throw new RuntimeException("刷新规则缓存失败: " + e.getMessage(), e);
        }
    }

    /**
     * 刷新所有规则缓存
     */
    public void refreshAllRulesCache() {
        log.info("刷新所有规则缓存");
        try {
            ruleCacheManager.refreshAllRules();
        } catch (Exception e) {
            log.error("刷新所有规则缓存失败", e);
            throw new RuntimeException("刷新所有规则缓存失败: " + e.getMessage(), e);
        }
    }

    /**
     * 启用/禁用转换规则
     * @param id 规则ID
     * @param enabled 是否启用
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateRuleStatus(Long id, Boolean enabled) {
        log.info("更新规则状态，ID: {}, enabled: {}", id, enabled);
        
        try {
            TransformRule rule = transformRuleMapper.selectById(id);
            if (rule == null) {
                throw new RuntimeException("规则不存在，ID: " + id);
            }

            rule.setEnabled(enabled);
            rule.setUpdateTime(LocalDateTime.now());
            
            int result = transformRuleMapper.updateById(rule);
            if (result <= 0) {
                throw new RuntimeException("更新规则状态失败");
            }

            // 更新版本号
            transformRuleMapper.incrementVersion(id);

            // 刷新缓存
            refreshRuleCacheAsync(rule.getRuleCode());
            
        } catch (Exception e) {
            log.error("更新规则状态失败，ID: {}", id, e);
            throw new RuntimeException("更新规则状态失败: " + e.getMessage(), e);
        }
    }

    /**
     * 校验规则DTO参数
     * @param ruleDTO 规则DTO
     */
    private void validateRuleDTO(TransformRuleDTO ruleDTO) {
        if (!StringUtils.hasText(ruleDTO.getRuleCode())) {
            throw new RuntimeException("规则编码不能为空");
        }
        if (!StringUtils.hasText(ruleDTO.getRuleName())) {
            throw new RuntimeException("规则名称不能为空");
        }
        if (!StringUtils.hasText(ruleDTO.getSourceType())) {
            throw new RuntimeException("源类型不能为空");
        }
        if (!StringUtils.hasText(ruleDTO.getTargetType())) {
            throw new RuntimeException("目标类型不能为空");
        }
    }

    /**
     * 转换字段映射DTO列表为实体列表
     * @param dtoList DTO列表
     * @param ruleId 规则ID
     * @return 实体列表
     */
    private List<FieldMappingRule> convertFieldMappingDTOs(List<FieldMappingRuleDTO> dtoList, Long ruleId) {
        List<FieldMappingRule> result = new ArrayList<>();
        
        for (int i = 0; i < dtoList.size(); i++) {
            FieldMappingRuleDTO dto = dtoList.get(i);
            FieldMappingRule entity = new FieldMappingRule();
            
            BeanUtils.copyProperties(dto, entity);
            entity.setRuleId(ruleId);
            entity.setCreateTime(LocalDateTime.now());
            entity.setUpdateTime(LocalDateTime.now());
            
            // 如果没有设置排序，使用索引作为排序
            if (entity.getSortOrder() == null) {
                entity.setSortOrder(i);
            }
            
            // 默认启用
            if (entity.getEnabled() == null) {
                entity.setEnabled(true);
            }
            
            // 默认非必填
            if (entity.getRequired() == null) {
                entity.setRequired(false);
            }
            
            result.add(entity);
        }
        
        return result;
    }

    /**
     * 转换实体为DTO
     * @param rule 转换规则实体
     * @param fieldMappings 字段映射实体列表
     * @return 转换规则DTO
     */
    private TransformRuleDTO convertToRuleDTO(TransformRule rule, List<FieldMappingRule> fieldMappings) {
        TransformRuleDTO dto = new TransformRuleDTO();
        BeanUtils.copyProperties(rule, dto);
        
        if (!CollectionUtils.isEmpty(fieldMappings)) {
            List<FieldMappingRuleDTO> mappingDTOs = fieldMappings.stream()
                .map(mapping -> {
                    FieldMappingRuleDTO mappingDTO = new FieldMappingRuleDTO();
                    BeanUtils.copyProperties(mapping, mappingDTO);
                    return mappingDTO;
                })
                .collect(Collectors.toList());
            dto.setFieldMappingRules(mappingDTOs);
        }
        
        return dto;
    }

    /**
     * 更新执行统计信息
     * @param ruleCode 规则编码
     */
    private void updateExecuteStatistics(String ruleCode) {
        try {
            // 异步更新执行统计，不影响主流程
            TransformRule rule = transformRuleMapper.selectByRuleCode(ruleCode);
            if (rule != null) {
                transformRuleMapper.incrementExecuteCount(rule.getId());
            }
        } catch (Exception e) {
            log.warn("更新执行统计失败，规则: {}", ruleCode, e);
        }
    }

    /**
     * 异步刷新规则缓存
     * @param ruleCode 规则编码
     */
    private void refreshRuleCacheAsync(String ruleCode) {
        // 这里可以使用异步执行，简化实现直接调用
        try {
            ruleCacheManager.refreshRule(ruleCode);
        } catch (Exception e) {
            log.warn("异步刷新缓存失败，规则: {}", ruleCode, e);
        }
    }
} 